// vim: foldmethod=marker : foldmarker=<<<,>>>
/*
 File: payload.c
 Generated-From: payload.nw
*/
#include "hooverPch.h"

#include "branch/branch.h"
#include "heap/heap.h"
#include "nis/payload.h"
#include "soddy/array.h"
v_t shutdown__nis_payload(nis_payload_p this) {
 empty__nis_payload(this);
 askFor__heap_steward(&justCommon__heap_steward,0,&this->pool.ni);
 askFor__heap_steward(&justCommon__heap_steward,0,&this->pool.handles);
 askFor__heap_steward(&justCommon__heap_steward,0,&this->pool.entries);
 };
hidden_q v_t cleanEntries(nis_entry_p entries, i_t qnt) {
 i_t i;
 for (i=0;i<qnt;i++) 
  askFor__heap_steward(&justCommon__heap_steward,0,&entries->extra);
 };

v_t empty__nis_payload(nis_payload_p this)
 { cleanEntries(this->entries,this->qnt); this->qnt=0; };
hidden_q i_t entrySize(PCE_NOTIFICATION_INFO_HEADER nih) {
  i_t size=(wlen(nih->pcent->lpszApplication)+1)*sizeof(WCHAR);
  if (nih->pcent->lpszArguments!=NULL)
    size+=(wlen(nih->pcent->lpszArguments)+1)*sizeof(WCHAR);
  if (nih->pceun!=NULL) {
/*    if (nih->pceun->pwszDialogTitle!=NULL) 
      size+=(wlen(nih->pceun->pwszDialogTitle)+1)*sizeof(WCHAR);*/
    if (nih->pceun->pwszDialogText!=NULL) 
      size+=(wlen(nih->pceun->pwszDialogText)+1)*sizeof(WCHAR);
  };
  return size;
};

hidden_q v_t fillEntry(nis_entry_p e, PCE_NOTIFICATION_INFO_HEADER nih, i1_p data) {
  e->application=CAST(PWSTR,data);
  data=(i1_p)wcpy(e->application,nih->pcent->lpszApplication);
  data+=sizeof(WCHAR);
  
  if (nih->pcent->lpszArguments==NULL) e->args=L"";
  else {
   e->args=CAST(PWSTR,data);
   data=(i1_p)wcpy(e->args,nih->pcent->lpszArguments);
   data+=sizeof(WCHAR); //skip NULL;
   };
 
  e->h=nih->hNotification;
  e->time.start=nih->pcent->stStartTime; e->time.stop=nih->pcent->stEndTime;
  SystemTimeToFileTime(&e->time.start,&e->timestamp.start);
  SystemTimeToFileTime(&e->time.stop,&e->timestamp.stop);

  e->type=nih->pcent->dwType; e->event=nih->pcent->dwEvent;

  e->display=L"";
  if (nih->pceun!=NULL) {
    if (nih->pceun->pwszDialogText!=NULL) {
      e->display=CAST(PWSTR,data);
      data=(i1_p)wcpy(e->display,nih->pceun->pwszDialogText);
      data+=sizeof(WCHAR); //skip NULL;
    };
/*    if (nih->pceun->pwszDialogTitle!=NULL) {
      e->display=CAST(PWSTR,data);
      data=(i1_p)wcpy(e->display,nih->pceun->pwszDialogTitle);
      data+=sizeof(WCHAR); //skip NULL;
    };*/
  };
 
 };

hidden_q i_t makeEntry(nis_payload_p this, HANDLE h, nis_entry_p e) {
 BOOL rs0; i_t rs; DWORD realSize;
 PCE_NOTIFICATION_INFO_HEADER hdr;

 rs0=CeGetUserNotification(h,this->pool.ni.size,&realSize,this->pool.ni.raw);
 SIGNAL(if(rs0),none,gain0);
 SIGNAL(if(realSize==0),none,fail0);
 
 rs=ensureNaive__spool_datum(&this->pool.ni,realSize,&justCommon__heap_steward);
 SIGNAL(unless(rs),none,fail0);

 rs0=CeGetUserNotification(h,this->pool.ni.size,&realSize,this->pool.ni.raw);
 SIGNAL(unless(rs0),none,fail0);

gain0:
 hdr=CAST(PCE_NOTIFICATION_INFO_HEADER,this->pool.ni.raw);
 rs=askFor__heap_steward(&justCommon__heap_steward,entrySize(hdr),&e->extra);
 SIGNAL(unless(rs),none,fail0);
 
 fillEntry(e,hdr,e->extra.data);
 return 1;

fail0: return 0;
 };

hidden_q i_t constructHandles(nis_payload_p this, PHANDLE * handles, i_p qnt) {
 BOOL rs0; i_t rs; DWORD count;

 rs0=CeGetUserNotificationHandles(NULL,0,&count);
 SIGNAL(unless(rs0),none,fail0);

 rs=ensureNaive__spool_datum(&this->pool.handles,count*sizeof(HANDLE),&justCommon__heap_steward);
 SIGNAL(unless(rs),none,fail0);

 rs0=CeGetUserNotificationHandles((PHANDLE)this->pool.handles.raw,count,&count);
 SIGNAL(unless(rs0),none,fail0);

 *handles=CAST(PHANDLE,this->pool.handles.raw);
 *qnt=count;
 return 1;
fail0: return 0;
 };

hidden_q i_t constructEntries(nis_payload_p this, PHANDLE handles, i_t qnt, nis_entry_pp entries) {
  i_t i,rs;
 
  rs=ensureNaive__spool_datum(&this->pool.entries,
    qnt*(sizeof(nis_entry_t)+3*sizeof(nis_entry_p)),
    &justCommon__heap_steward);
  SIGNAL(unless(rs),none,fail0);
  this->sortBy.none=padd(this->pool.entries.raw,sizeof(nis_entry_t)*qnt);
  this->sortBy.date=padd(this->sortBy.none,sizeof(nis_entry_p)*qnt);
  this->sortBy.name=padd(this->sortBy.date,sizeof(nis_entry_p)*qnt);
  mzero(this->pool.entries.raw,this->pool.entries.size);

  for (i=0;i<qnt;i++) {
    nis_entry_p curr=CAST(nis_entry_p,this->pool.entries.raw)+i;
    rs=makeEntry(this,handles[i],curr); 
    SIGNAL(unless(rs),none,fail1);
    this->sortBy.none[i]=this->sortBy.date[i]=this->sortBy.name[i]=curr;
  };
  *entries=CAST(nis_entry_p,this->pool.entries.raw);
  return 1;
 
fail1: cleanEntries(CAST(nis_entry_p,this->pool.entries.raw),i);
fail0: return 0;
};

hidden_q is_t compareByName(nis_entry_pp l, nis_entry_pp r) 
 { return _wcsicmp((*l)->application,(*r)->application); };

#define PTR_SWAP(l,r) do { v_p aux=*l; *l=*r; *r=aux; } while(0)

hidden_q v_t sortByName(nis_payload_p this) {
  QSORT_X1__soddy_array(nis_entry_pp,this->sortBy.name,this->qnt,
    compareByName,PTR_SWAP);
}

hidden_q is_t compareByDate(nis_entry_pp l, nis_entry_pp r) {
  FILETIME * ltm=&(*l)->timestamp.start, * rtm=&(*r)->timestamp.start;
  DWORD rs=ltm->dwHighDateTime-rtm->dwHighDateTime;
  if (rs==0) rs=ltm->dwLowDateTime-rtm->dwLowDateTime;
  if (rs!=0) {
    if (ltm->dwHighDateTime==0 && ltm->dwLowDateTime==0) rs=1;
    if (rtm->dwHighDateTime==0 && rtm->dwLowDateTime==0) rs=-1;
  }
  return rs;
};

hidden_q v_t sortByDate(nis_payload_p this) {
  QSORT_X1__soddy_array(nis_entry_pp,this->sortBy.date,this->qnt,
    compareByDate,PTR_SWAP);
}

i_t update__nis_payload(nis_payload_p this) {
 i_t rs,qnt; PHANDLE handles; nis_entry_p entries;

 empty__nis_payload(this);
 
 rs=constructHandles(this,&handles,&qnt);
 SIGNAL(unless(rs),none,fail0);

 rs=constructEntries(this,handles,qnt,&entries);
 SIGNAL(unless(rs),none,fail0);

 this->handles=handles; this->entries=entries; this->qnt=qnt;
 sortByName(this);
 sortByDate(this);
 return 1;
fail0: this->qnt=0; return 0;
 };
v_t remove__nis_payload(nis_payload_p this, i_t index) {
 nis_entry_p e;
 if (index>=this->qnt) return;
 e=this->entries+index; CeClearUserNotification(e->h);
 };
